package fregat.base.net;


import java.io.*;

import fregat.base.util.Logger;

/**
 * Default protocol class that receives until carriage return and/or line feed
 * and adds system's line separator to data before sending.
 *
 * @author Alexander Mann <br><b><i>ECO_L O G</i> &nbsp Logistiksysteme GmbH</b>
 * @version 1.0
 */
public class DefaultProtocol extends Protocol {

  private BufferedReader reader;
  private PrintStream stream;
  private String delimiter;

  /**
   * Creates a new default protocol with the given name.
   *
   * @param name Name of instance that uses the protocol
   */
  public DefaultProtocol(String name) {
    super(name);
  }

  /**
   * Creates a new default protocol with the given name and adds the
   * given end delimiter when sending instead of the system's line separator.
   * eg. if CR(\r) should be used instead of system's CRLF(\r\n).
   * @param name Name of instance that uses the protocol
   * @param delimiter End delimiter for sending
   */
  public DefaultProtocol(String name, String delimiter)
  {
    super(name);
    this.delimiter = delimiter;
  }

  /**
   * Receives a line from the input stream.
   *
   * @param in Input stream
   * @return Received data(including header)
   * @throws IOException
   */
  public byte[] receive(InputStream in) throws IOException {

    // create reader once
    if(reader == null) {
      reader = new BufferedReader(new InputStreamReader(in));
    }

    // read to next line feed or carriage return
    String data = reader.readLine();

    byte[] receivedData = null;

    if (data != null) {
      receivedData = data.getBytes();
    }

    return receivedData;
  }

  /**
   * Adds the system line separator as end delimiter to the given data and sends it to the output
   * stream.
   *
   * @param out      Output stream
   * @param sendData Data to be sent
   * @return True, if send was success
   */
  public boolean send(OutputStream out, byte[] sendData) {
    try {
      // convert to print stream
      if (out instanceof PrintStream) {
        stream = (PrintStream) out;
      } else {
        if(stream == null) {
          stream = new PrintStream(out);
        }
      }

      // write data
      stream.write(sendData);


      if(delimiter == null) {
        // add system line separator
        stream.println();
      } else {
        // add specified delimiter
        stream.write(delimiter.getBytes());
      }

      return !stream.checkError();

    } catch (IOException ex) {
      Logger.getDefaultCategory().error("DefaultProtocol, send(...)", ex);
      return false;
    }
  }

  /**
   * Connection was closed.
   */
  public void close() {
    try {
      reader.close();
    } catch(Exception ex) {}
    try {
      stream.close();
    } catch(Exception ex) {}

    reader = null;
    stream = null;
  }
}
